package cn.kgc.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.kgc.base.BaseInfoProperties;
import cn.kgc.entity.Users;
import cn.kgc.excpetion.GraceException;
import cn.kgc.grace.result.GraceJSONResult;
import cn.kgc.grace.result.ResponseStatusEnum;
import cn.kgc.service.UsersService;
import cn.kgc.utils.JwtUtil;
import cn.kgc.vo.UsersVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static cn.kgc.base.SystemConstant.LOGIN_TYPE_SAAS;
import static cn.kgc.base.SystemConstant.ROLE_JOB_SEEKERS;

/**
 * @author wangyue
 * @version 1.0
 */
@RestController
@RequestMapping("/sass")
@Validated
@Slf4j
@Api(tags="二维码扫码登录模块")
public class SaasPassportController extends BaseInfoProperties {

    @Resource
    private UsersService usersService;

    @Resource
    private JwtUtil jwtUtil;

    @GetMapping("/getQRToken")
    @ApiOperation(value = "获得二维码令牌")
    public GraceJSONResult  getQRToken(){
        //1 生成二维码令牌字符串
        String token = UUID.randomUUID().toString();
        //2 将二维码令牌的字符串保存到Redis中
        String key=SAAS_PLATFORM_LOGIN_TOKEN+token;
        redisUtil.set(key,token,5, TimeUnit.MINUTES);
        //3 保存二维码令牌的状态
        String readKey=SAAS_PLATFORM_LOGIN_TOKEN_READ+token;
        //值规则 以"0,"开头 例如 0,38942jker34jsferl23r34   "0,"表示此二维码令牌未读
        redisUtil.set(readKey,"0,"+token,5, TimeUnit.MINUTES);
        //4 返回二维码令牌字符串
        return GraceJSONResult.ok(token);
    }


    @PostMapping("/scanCode")
    @ApiOperation(value="扫描登录二维码接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name ="qrToken",value="二维码令牌"),
            @ApiImplicitParam(name ="appLoginToken",value="app端登录token")
    })
    public GraceJSONResult scanCode(
            @RequestParam(name = "qrToken") String qrToken,
            @RequestHeader(name = "token") String appLoginToken
    ){
        //1 参数的非空验证
       if(StrUtil.isBlank(qrToken)){
           GraceException.display(ResponseStatusEnum.SAAS_USER_LOGIN_TOKEN_ERROR);
       }
       if(StrUtil.isBlank(appLoginToken)){
           GraceException.display(ResponseStatusEnum.SAAS_USER_LOGIN_APP_TOKEN_ERROR);
       }
        //2 验证二维码令牌是否错误或者已经过期
        String key=SAAS_PLATFORM_LOGIN_TOKEN+qrToken;
        if(!redisUtil.hasKey(key)){
            GraceException.display(ResponseStatusEnum.SAAS_USER_LOGIN_TOKEN_ERROR);
        }
       //3 判断app端登录的令牌是否正确
        try {
            //(1) 令牌是否正确
            String userId= jwtUtil.getUserId(appLoginToken);
            //(2) 令牌对应的用户是否是招聘者
            Users users = usersService.getById(userId);
            if(users==null){
                GraceException.display(ResponseStatusEnum.SASS_USER_NOT_EXIST_ERROR);
            }
            if(users.getRole() == ROLE_JOB_SEEKERS){
                GraceException.display(ResponseStatusEnum.SASS_USER_LOGIN_ROLE_ERROR);
            }
        } catch (Exception e) {
            GraceException.display(ResponseStatusEnum.SAAS_USER_LOGIN_APP_TOKEN_ERROR);
        }
       //4 生成预登录令牌保存预登录令牌同时将二维码令牌标识为已经被扫描
       String preToken = UUID.randomUUID().toString();
       String readKey= SAAS_PLATFORM_LOGIN_TOKEN_READ+qrToken;
       redisUtil.set(readKey,"1,"+preToken,5, TimeUnit.MINUTES);
       //5 删除已经被扫描过的二维码令牌
       redisUtil.delete(key);
       //5 返回预登录令牌
        return GraceJSONResult.ok(preToken);
    }

    @PostMapping("/codeHashBeanRead")
    @ApiOperation(value="二维码令牌是否被扫描")
    @ApiImplicitParam(name="qrToken",value = "二维码令牌")
    public GraceJSONResult codeHashBeanRead(String qrToken){
        List<String> list=new ArrayList<>();
        //1 二维码令牌过期
        String key=SAAS_PLATFORM_LOGIN_TOKEN+qrToken;
        if(!redisUtil.hasKey(key)){
            //向前端返回空的集合
            return GraceJSONResult.ok(list);
        }
        //2 二维码令牌已经被扫描过
        String readKey=SAAS_PLATFORM_LOGIN_TOKEN_READ+qrToken;
        String string = (String)redisUtil.get(readKey);
        if(string.startsWith("1,")){
            //向前端返回包含"0"字符串的集合
            list.add("0");
            return GraceJSONResult.ok(list);
        }
        //3 二维码令牌未被扫描过  向前端返回包含"1"字符串的集合
        list.add("1");
        return GraceJSONResult.ok(list);
    }

    @PostMapping("/goQRLogin")
    @ApiOperation(value="用户确认登录")
    @ApiImplicitParams({
            @ApiImplicitParam(name ="preToken",value="预登录令牌"),
            @ApiImplicitParam(name ="qrToken",value="二维码令牌"),
            @ApiImplicitParam(name ="appLoginToken",value="app端登录token")
    })
    public GraceJSONResult goQRLogin(
            @RequestHeader(name = "token") String appLoginToken,
            String preToken,
            String qrToken
    ){
       //判断预登录令牌是否正确,如果预登录令牌错误,返回错误信息.
       if(StrUtil.isBlank(preToken)){
           GraceException.display(ResponseStatusEnum.SAAS_USER_LOGIN_PRE_TOKEN_ERROR);
       }
       if(StrUtil.isBlank(qrToken)){
           GraceException.display(ResponseStatusEnum.SAAS_USER_LOGIN_TOKEN_ERROR);
       }
       //获得二维码令牌对应的预登录令牌
       String readKey=SAAS_PLATFORM_LOGIN_TOKEN_READ+qrToken;
       if(redisUtil.get(readKey)==null){
           GraceException.display(ResponseStatusEnum.SAAS_USER_LOGIN_ERROR);
       }
       //如果根据二维码令牌获得到了预登录令牌
        String preTokenRedis = (String)redisUtil.get(readKey);
        //判断用户传入的预登录令牌是否正确,如果错误返回错误信息
        if(!("1,"+preToken).equals(preTokenRedis)){
            GraceException.display(ResponseStatusEnum.SAAS_USER_LOGIN_ERROR);
        }
        //解析app端登录的token,获得用户的id,根据用户的id查询用户的信息。将此用户信息保存到Redis中
        try {
            String userId = jwtUtil.getUserId(appLoginToken);
            Users loginUser = usersService.getById(userId);
            String sassTempLoginUserKey=REDIS_SAAS_USER_INFO_TEMP+qrToken;
            redisUtil.set(sassTempLoginUserKey,loginUser,10,TimeUnit.SECONDS);
            //将redis中二维码令牌的状态删除
            redisUtil.delete(readKey);
        } catch (Exception e) {
            GraceException.display(ResponseStatusEnum.SAAS_USER_LOGIN_APP_TOKEN_ERROR);
        }
        return GraceJSONResult.ok();
    }

    @PostMapping ("/checkLogin")
    @ApiOperation(value="管理页面检查是否登录成功")
    @ApiImplicitParam(name="qrToken",value="二维码令牌")
    public GraceJSONResult checkLogin(String qrToken){
        //1 根据二维码令牌获得用户的信息
        String userKey=REDIS_SAAS_USER_INFO_TEMP+qrToken;
        if(!redisUtil.hasKey(userKey)){
            //如果用户的信息为空,返回一个data为null的GraceJSONResult对象
            return GraceJSONResult.ok();
        }
        //2 如果不为空,生成后台管理端的登录令牌。
        Users loginUsers=(Users) redisUtil.get(userKey);
        String token=jwtUtil.createToken(loginUsers.getId(), LOGIN_TYPE_SAAS);
        //将令牌和登录的用户信息给管理后台的页面
        UsersVO usersVO=new UsersVO();
        BeanUtil.copyProperties(loginUsers,usersVO);
        usersVO.setToken(token);
        return GraceJSONResult.ok(usersVO);
    }
}